package com.yedean.factory.annotation;

import cn.hutool.core.bean.BeanUtil;
import com.yedean.factory.BeanFactory;
import com.yedean.factory.BeanFactoryAware;
import com.yedean.factory.BeansException;
import com.yedean.factory.ConfigurableListableBeanFactory;
import com.yedean.factory.aop.InstantiationAwareBeanPostProcessor;
import com.yedean.factory.property.PropertyValues;
import com.yedean.factory.utils.ClassUtils;

import java.lang.reflect.Field;

public class AutowiredAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {

    private ConfigurableListableBeanFactory beanFactory;
    
    
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        // 1. 处理注解 @Value
        Class<?> clazz = bean.getClass();
        clazz = ClassUtils.isCglibProxyClass(clazz) ? clazz.getSuperclass() : clazz;

        Field[] fields = clazz.getDeclaredFields();

        for (Field field : fields) {
            Value valueAnnotation = field.getAnnotation(Value.class);
            if (null!=valueAnnotation){
                String value = valueAnnotation.value();
                value=beanFactory.resolveEmbeddedValue(value);
                BeanUtil.setFieldValue(bean,field.getName(),value);
            }
        }

        // 2. 处理注解 @Autowired
        for (Field field : fields) {
            Autowired annotation = field.getAnnotation(Autowired.class);
            if (null!=annotation){
                Class<?> type = field.getType();
                String dependentBeanName;
                Object dependentBean;
                Qualifier qualifier = field.getAnnotation(Qualifier.class);
                if (null!=qualifier){
                    dependentBeanName = qualifier.value();
                    dependentBean=beanFactory.getBean(dependentBeanName,type);
                }else {
                    dependentBean=beanFactory.getBean(type);
                }
                BeanUtil.setFieldValue(bean,field.getName(),dependentBean);
            }
        }
        
        return pvs;

    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory=(ConfigurableListableBeanFactory) beanFactory;
    }
}
